package org.sqltomongo.orm;

import cn.org.wangchangjiu.sqltomongo.core.parser.SelectSQLTypeParser;
import cn.org.wangchangjiu.sqltomongo.core.parser.data.PartSQLParserData;
import cn.org.wangchangjiu.sqltomongo.core.util.SqlCommonUtil;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.sqltomongo.executor.Executor;
import org.springframework.lang.Nullable;

import java.util.List;
import java.util.Map;


public class DefaultSqlSession implements SqlSession {


    private final Configuration configuration;

    private final Executor executor;

    private Map<String, XNode> mapperElement;

    public DefaultSqlSession(Configuration configuration, Executor executor) {
        this.configuration = configuration;
        this.executor = executor;
        this.mapperElement = configuration.getMapperElement();
    }

    @Override
    public Configuration getConfiguration() {
        return this.configuration;
    }

    @Override
    public PartSQLParserData sqlParserData(String sql, Object... parameters) {
        return executor.sqlParserData(sql, parameters);
    }

    @Override
    public Object execute(String statement, Class returnType, Class actualType, Object... parameters) {

        XNode xNode = mapperElement.get(statement);
        if(xNode.getSqlType() == SqlCommonUtil.SqlType.SELECT){
            // 查询
            if(returnType == List.class){
                // 集合
                return selectList(statement, actualType, parameters);
            } else {
                return selectOne(statement, returnType, parameters);
            }
        }


        return null;
    }

    @Override
    public <T> T selectOne(String statement, Class<T> returnType, @Nullable Object... parameters) {
        String sql = statement;
        if(!SqlCommonUtil.statementIsSQL(statement)){
            XNode xNode = mapperElement.get(statement);
            sql = xNode.getSql();
        }
        return executor.selectOne(sql, returnType, parameters);
    }


    @Override
    public <T> List<T> selectList(String statement, Class<T> returnType, @Nullable Object... parameters) {
        String sql = statement;
        if(!SqlCommonUtil.statementIsSQL(statement)){
            XNode xNode = mapperElement.get(statement);
            sql = xNode.getSql();
        }
        return executor.selectList(sql, returnType, parameters);
    }

    public static class DefaultSqlSessionBuilder {

        public static DefaultSqlSession build(MongoTemplate mongoTemplate,
                                              Configuration configuration) {
            Configuration.InterceptorPartSQLParserBuilder parserBuilder = new Configuration.InterceptorPartSQLParserBuilder();
            Configuration.InterceptorAnalyzerBuilder analyzerBuilder = new Configuration.InterceptorAnalyzerBuilder();
            return new DefaultSqlSession(configuration, configuration.newExecutor(mongoTemplate,
                    new SelectSQLTypeParser(parserBuilder, analyzerBuilder)));
        }
    }

}
